package cn.cboard.gateway;

import java.util.ArrayList;
import java.util.List;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;

/**
 * @author
 *
 * 
 * Class to create/manufacture view definitions from property files
 * 
 * @see ViewDefn
 * 
 */
public class ViewDefnFactory {

	public interface Consts {
		public static final String MAX_ROWS = "maxrows";
		public static final String FETCH_SIZE = "fetchsize";
		public static final String CONVERTER = "converter";
		public static final String DBMS_VIEW = "view";
		public static final String COLUMNS = "columns";
		public static final String WHERE_CLAUSE = "where";
		public static final String ORDER_BY_CLAUSE = "orderby";
	}

	public static ViewDefnFactory get() {
		return new ViewDefnFactory();
	}

	/**
	* Create a ViewDefn from an entry in a properties file
	*/
	public ViewDefn createViewDefn(String baseName, String viewName) {
		ResourceBundle bundle = PropertyResourceBundle.getBundle(baseName);
		return createViewDefn(bundle, viewName);
	}

	/**
	 * Create a ViewDefn from an entry in a resource bundle
	 */
	public ViewDefn createViewDefn(ResourceBundle bundle, String viewName) {

		PropertyUtil props = PropertyUtil.get(bundle, viewName);

		// get view (minimum required attr)
		String dbmsview = props.getAsString(Consts.DBMS_VIEW);

		if (dbmsview == null)
			return null;

		ViewDefn d = (ViewDefn)createDefn();
		d.setViewName(dbmsview);
		// get columns

		String s = props.getAsString(Consts.COLUMNS);
		if (s != null) {
			List columns = PropertyUtil.toList(s);

			String[] cols = (String[]) columns.toArray(new String[0]);
			d.setColumnNames(cols);
		}
		// get where
		s = props.getAsString(Consts.WHERE_CLAUSE);
		if (s != null) {
			d.setWhereClause(s);
		}

		//		get where phrases

		s = props.getAsString(Consts.WHERE_CLAUSE);
		//d.setWhereClause(s);
		int index = 1;
		List phrases = new ArrayList();
		if (s != null) {
			WhereDesc wd = new WhereDesc(s);
			// read other stuff tbd
			phrases.add(wd);

			// look for parameters
			s =
			props.getAsString(

					PropertyUtil.concatKeys(Consts.WHERE_CLAUSE,Consts.COLUMNS)
					);
			if (s != null) {
				List paramList = PropertyUtil.toList(s);
				ColumnDesc[] params = parseColumns(paramList);
				wd.setParams(params);
			}
		}
		while (true) {
			String whereKey =
				PropertyUtil.concatKeys(viewName, Consts.WHERE_CLAUSE + index);
			s = props.getAsStringNoContext(whereKey);
			if (s == null) {
				break;
			}
			WhereDesc wd = new WhereDesc(s);

			phrases.add(wd);
			// look for parameters
			s =
			props.getAsString(
			
					PropertyUtil.concatKeys(whereKey, Consts.COLUMNS)
			);
			if (s != null) {
				List paramList = PropertyUtil.toList(s);
				ColumnDesc[] params = parseColumns(paramList);
				wd.setParams(params);
			}
			++index;
		}
		d.setWherePhrases((WhereDesc[]) phrases.toArray(new WhereDesc[0]));

		// get orderby

		s = props.getAsString(Consts.ORDER_BY_CLAUSE);
		if (s != null) {
			List columns = PropertyUtil.toList(s);
			ColumnDesc[] orderByColumns = parseColumns(columns);
			d.setOrderBy(orderByColumns);
		}

		// get max rows
		s = props.getAsString(Consts.MAX_ROWS);
		if (s != null) {
			d.setMaxRows(PropertyUtil.getAsInt(s));
		}
		// get fetch hints
		s = props.getAsString(Consts.FETCH_SIZE);
		if (s != null) {
			d.setFetchSize(PropertyUtil.getAsInt(s));
		}
		// get converter
		s = props.getAsString(Consts.CONVERTER);

		if (s != null) {
			try {
				Class c = Class.forName(s);
				ResultSetConverter converter =
					(ResultSetConverter) c.newInstance();
				d.setConverter(converter);
			} catch (Exception e) {
			}
		}

		return d;

	}

	public static ColumnDesc[] parseColumns(List columns) {
		String[] cols = (String[]) columns.toArray(new String[0]);
		ColumnDesc[] descs = new ColumnDesc[cols.length];
		for (int i = 0; i < descs.length; ++i) {
			descs[i] = ColumnDesc.toColumnDesc(cols[i]);
		}
		return descs;

	}
	public SQLDefn createDefn() {
			return new ViewDefn();
		}
}
